package Game;
import java.io.File;
import java.io.Serializable;
import java.util.*;

/**
 * This contains all the information about the locations in the game
 * 
 * @author Ryan Goodrich
 * @version 1.0
 */
public class LocationList extends FileInput{

	/**
	 * Create the location list from the input file
	 */
	private static String folder = System.getProperty("user.dir")+ File.separator;
	public LocationList() {
		super(folder+"support"+File.separator+"Locations.txt");
	}
	
	/**
	 * Returns the name of the location
	 * 
	 * @param locationId The id of the location
	 * @return Name of the location
	 */
	public String getLocationName(int locationId) {
		if (!checkIndex(locationId))
			return null;
		return getRawDataAt(locationId).get("name");
	}
	
	/**
	 * Returns the x position of the location
	 * 
	 * @param locationId The id of the location
	 * @return The x position
	 */
	public int getXPosistion(int locationId) {
		if (!checkIndex(locationId))
			return 0;
		return Integer.parseInt(getRawDataAt(locationId).get("location").split("[,]")[0].replace('(', ' ').trim());
	}
	
	/**
	 * Returns the y position of the location
	 * 
	 * @param locationId The id of the location
	 * @return The y position
	 */
	public int getYPosistion(int locationId) {
		if (!checkIndex(locationId))
			return 0;
		return Integer.parseInt(getRawDataAt(locationId).get("location").split("[,]")[1].replace(')', ' ').trim());
	}
	
	/**
	 * Return an array of next location ids and relative distances
	 * to the locaiton id passed
	 * 
	 * @param locationId The id of the location
	 * @return Array of key/value pairs containg the relative distance and
	 * id of all surrounding locations
	 * 		id => next locations id
	 * 		distance => next locations distance from passed id
	 */
	public ArrayList<HashMap<String, Integer>> getSurroundingLocations(int locationId) {
		if (!checkIndex(locationId))
			return null;
		
		// create return data structure
		ArrayList<HashMap<String, Integer>> returnMapping = new ArrayList<HashMap<String, Integer>>();
		HashMap<String, Integer> locationMap = null;
		
		// create arrays of all locations and distances
		String[] locations = getRawDataAt(locationId).get("next_loc").split("[|_|]");
		String[] distances = getRawDataAt(locationId).get("next_loc_dist").split("[|_|]");
		String[] costs = getRawDataAt(locationId).get("next_loc_price").split("[|_|]");
		String[] over_water = getRawDataAt(locationId).get("next_loc_over_water").split("[|_|]");
		
		for (int i = 0; i < locations.length; i++) {
			 
			// exit if gets larger then the distance array
			if (i == distances.length)
				break;
			if (distances[i].equals(""))
				continue;
			// add information to hash map and return array
			locationMap = new HashMap<String, Integer>();
			locationMap.put("id", getIdOf("name", locations[i]));
			locationMap.put("distance", Integer.parseInt(distances[i]));
			locationMap.put("price", costs.length < i ? 0 : Integer.parseInt(costs[i]));
			locationMap.put("water", over_water.length < i ? 0 : Integer.parseInt(over_water[i]));
			
			returnMapping.add(locationMap);
		}
		return returnMapping;
	}
	
	/**
	 * Determine the distance between two locations that are next locations
	 * of each other
	 * 
	 * @param currentLocationId The location that is used as the base point
	 * @param nextLocationId The location that you want to know the distance to
	 * @return Distance to next location, -1 if the location is not valid or cannot
	 * 		be found
	 */
	public int getDistanceTo(int currentLocationId, int nextLocationId) {
		if (!checkIndex(currentLocationId) || !checkIndex(nextLocationId))
			return -1;
		
		for (HashMap<String, Integer> surrondingLocation : getSurroundingLocations(currentLocationId))
			if (surrondingLocation.get("id") == nextLocationId)
				return surrondingLocation.get("distance");
		return -1;
	}
	
	/**
	 * Return the percentage of seclusion of the location
	 * 
	 * @param locationId Location being looked up
	 * @return Percent that the location is secluded
	 */
	public double getSeclusionFactor(int locationId) {
		if (!checkIndex(locationId))
			return -1;
		return Double.parseDouble(getRawDataAt(locationId).get("seclusion_factor")) / 100;
	}
	
	/**
	 * Return if there is a store present at the location
	 * 
	 * @param locationId Location being looked up
	 * @return If the locaiton has a store or not
	 */
	public boolean hasStore(int locationId) {
		if (!checkIndex(locationId))
			return false;
		String storeCheck = getRawDataAt(locationId).get("store");
		if (storeCheck == null)
			return false;
		return storeCheck.equalsIgnoreCase("true");
	}
	
	/**
	 * Return if the location is inside of the united states
	 * 
	 * @param locationId Location being looked up
	 * @return If the location is in the usa
	 */
	public boolean inUSA(int locationId) {
		if (!checkIndex(locationId))
			return false;
		String inUSA = getRawDataAt(locationId).get("in_usa");
		if (inUSA == null)
			return false;
		return !inUSA.equalsIgnoreCase("0");
	}
	
	/**
	 * Return if the location is a bridge
	 * 
	 * @param locationId Location being looked up
	 * @return If the location is a bride
	 */
	public boolean isBridge(int locationId) {
		if (!checkIndex(locationId))
			return false;
		String checking = getRawDataAt(locationId).get("is_bridge");
		if (checking == null)
			return false;
		return !checking.equalsIgnoreCase("0");
	}
	
	/**
	 * Return if the location is a border crossing
	 * 
	 * @param locationId Location being looked up
	 * @return If the location is a border crossing
	 */
	public boolean isCrossing(int locationId) {
		if (!checkIndex(locationId))
			return false;
		String checking = getRawDataAt(locationId).get("is_border_crossing");
		if (checking == null)
			return false;
		return !checking.equalsIgnoreCase("0");
	}
}
